#ifndef STATSxx_OPTIMIZATION_EA_EVOLUTION_HPP
#define STATSxx_OPTIMIZATION_EA_EVOLUTION_HPP

// STL
#include <functional>                             // std::function<>
#include <vector>                                 // std::vector<>

// this
#include "statsxx/optimization/EA/EAParam.hpp"    // EAParam
#include "statsxx/optimization/EA/Individual.hpp" // Individual
#include "statsxx/optimization/EA/Population.hpp" // Population
#include "statsxx/optimization/EA/utility.hpp"    // calc_genome_distance()


std::vector<Individual> get_elite_individuals(
                                              const int                  n,
                                              // -----
                                              const bool                 feasible,
                                              // =====
                                              const Population          &_population,
                                              // -----
                                              const std::vector<double> &f,
                                              const std::vector<double> &v
                                              );
#include "statsxx/optimization/EA/evolution/get_elite_individuals.cpp"


void crossover_kpoint(
                      const Individual &mom,
                      const Individual &dad,
                      // -----
                      Individual       &child1,
                      Individual       &child2,
                      // -----
                      const EAParam    &param
                      );
#include "statsxx/optimization/EA/evolution/crossover_kpoint.cpp"


void mutate(
            Individual                                                    &child,
            // -----
            std::function<double(const int, const std::vector<double> &)>  new_gene,
            std::function<double(const int, const std::vector<double> &)>  mutate_gene,
            // -----
            const EAParam                                                 &param
            );
#include "statsxx/optimization/EA/evolution/mutate.cpp"


Population reproduce(
                     const Population                                                    &population,
                     // -----
                     const std::vector<double>                                           &f,
                     const std::vector<double>                                           &v,
                     // =====
                     const std::function<double(const int, const std::vector<double> &)> &new_gene,
                     const std::function<double(const int, const std::vector<double> &)> &mutate_gene,
                     // =====
                     const EAParam                                                       &param
                     );
#include "statsxx/optimization/EA/evolution/reproduce.cpp"

#endif
